package com.yaodian100.ec.report.rank.service.impl;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.yaodian100.core.common.service.impl.DomainServiceImpl;
import com.yaodian100.ec.category.entity.Category;
import com.yaodian100.ec.category.service.CategoryService;
import com.yaodian100.ec.product.entity.Product;
import com.yaodian100.ec.product.service.ProductService;
import com.yaodian100.ec.rank.entity.ReportProductClick;
import com.yaodian100.ec.rank.entity.ReportProductClickPrimaryKey;
import com.yaodian100.ec.report.rank.service.ReportProductClickService;

public class ReportProductClickServiceImpl extends DomainServiceImpl<ReportProductClick> implements ReportProductClickService {
	
	private static final Long DEFAULT_SORT = Long.valueOf(100);
	private static final Long DELETE_SORT = Long.valueOf(200);
	
	@Autowired
	private ProductService productService;
	@Autowired
	private CategoryService categoryService;
	
	@Transactional(readOnly = false)
	public void save(Long categoryId, List<String> productIdList, List<Boolean> newRecordMarkList, int retroDays, List<String> deleteProductIdList, List<String> deleteCategoryIdList) {
		if (productIdList.size() != newRecordMarkList.size()) {
			throw new RuntimeException("介面控制有問題，productIdList 與 newRecordMarkList 長度必需相同");
		}
		
		Date baseDate = ViewReportProductClickServiceImpl.baseDate(retroDays);
		
		resetSortInSameSecondLevelCategory(categoryId, baseDate);
		
		for (String productId: productIdList) {
			int index = productIdList.indexOf(productId);
			Long sort = new Long(index);
			boolean isNewRecord = newRecordMarkList.get(index).booleanValue();
			Product product = getProductService().get(productId);
			Long categoryIdOfProduct = new Long(product.getMainCategoryID());
			
			if (isNewRecord) {
				ReportProductClick newRecord = new ReportProductClick();
				
				ReportProductClickPrimaryKey pk = new ReportProductClickPrimaryKey();
				pk.setCategoryId(categoryIdOfProduct);
				pk.setProductId(productId);
				pk.setComputeDate(baseDate);
				
				newRecord.setPrimaryKey(pk);
				newRecord.setSort(sort);
				
				getDao().saveOrUpdate(newRecord);
			}
			
			Map<String, Serializable> attrs = new HashMap<String, Serializable>();
			attrs.put("sort", sort);
			attrs.put("productId", productId);
			attrs.put("computeDate", baseDate);
			int updatedRecordCount = getDao().executeUpdate("ReportProductClick.updateSortByProductIdAfterDate", attrs);
			logger.debug("updated records: " + new Integer(updatedRecordCount).toString());
			
		}
		
		deleteBatch(deleteProductIdList, deleteCategoryIdList, baseDate);
	}
	
	private int deleteBatch(List<String> deleteProductIdList, List<String> deleteCategoryIdStringList, Date computeDate) {
		if (null == deleteProductIdList) {
			return 0;
		}
		if (null == deleteCategoryIdStringList) {
			return 0;
		}
		if (deleteProductIdList.size() != deleteCategoryIdStringList.size()) {
			return 0;
		}
		
		logger.debug(String.valueOf(deleteProductIdList.size()));
		logger.debug(String.valueOf(deleteCategoryIdStringList.size()));
		
		int result = 0;
		for (String productId: deleteProductIdList) {
			Map<String, Serializable> attrs = new HashMap<String, Serializable>();
			int index = deleteProductIdList.indexOf(productId);
			Long categoryId = Long.valueOf(deleteCategoryIdStringList.get(index));
			
			attrs.put("productId", productId);
			attrs.put("categoryId", categoryId);
			attrs.put("computeDate", computeDate);
			result = getDao().executeUpdate("ReportProductClick.deleteByProductCategoryIdAfterDate", attrs);
			logger.debug("updated records: " + new Integer(result).toString());
		}
		
		return result;
	}
	
	private void markAsDeleteForBatch(List<String> deleteProductIdList, List<String> deleteCategoryIdStringList, Date computeDate) {
		if (null == deleteProductIdList) {
			return;
		}
		if (null == deleteCategoryIdStringList) {
			return;
		}
		if (deleteProductIdList.size() != deleteCategoryIdStringList.size()) {
			return;
		}
		
		logger.debug(String.valueOf(deleteProductIdList.size()));
		logger.debug(String.valueOf(deleteCategoryIdStringList.size()));
		
		for (String productId: deleteProductIdList) {
			Map<String, Serializable> attrs = new HashMap<String, Serializable>();
			int index = deleteProductIdList.indexOf(productId);
			Long categoryId = Long.valueOf(deleteCategoryIdStringList.get(index));
			
			attrs.put("sort", DELETE_SORT);
			attrs.put("productId", productId);
			attrs.put("categoryId", categoryId);
			attrs.put("computeDate", computeDate);
			int updatedRecordCount = getDao().executeUpdate("ReportProductClick.updateSortByProductCategoryIdAfterDate", attrs);
			logger.debug("updated records: " + new Integer(updatedRecordCount).toString());
		}
	}

	private void resetSortInSameSecondLevelCategory(Long categoryId, Date computeDate) {
		
		Map<String, Serializable> attrsBySecondCategoryId = new HashMap<String, Serializable>();
		attrsBySecondCategoryId.put("categoryId", categoryId.toString());
		attrsBySecondCategoryId.put("computeDate", computeDate);
		
		List<Long> categoryIdListOfSameSecondCategoryId = getDao().getNameQuery("ViewReportProductClick.selectDistinctCategoryListAfterDateBySecondCategoryId", attrsBySecondCategoryId, 0, -1);
		for (Long matchedCategoryId: categoryIdListOfSameSecondCategoryId) {
			
			Map<String, Serializable> attrsByCategoryId = new HashMap<String, Serializable>();
			attrsByCategoryId.put("sort", DEFAULT_SORT);
			attrsByCategoryId.put("categoryId", matchedCategoryId);
			attrsByCategoryId.put("computeDate", computeDate);
			int resetRecordCountByCategoryId = getDao().executeUpdate("ReportProductClick.updateSortByCategoryIdAfterDate", attrsByCategoryId);
			logger.debug("reset records: " + new Integer(resetRecordCountByCategoryId).toString());
			
		}
	}

	public ProductService getProductService() {
		return this.productService;
	}
	public void setProductService(ProductService productService) {
		this.productService = productService;
	}

	private CategoryService getCategoryService() {
		return this.categoryService;
	}
	private void setCategoryService(CategoryService categoryService) {
		this.categoryService = categoryService;
	}
	
}
